package com.vhall.component.service.goods.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vhall.component.dao.goods.GoodsMapper;
import com.vhall.component.dao.goods.LiveGoodsMapper;
import com.vhall.component.dao.goods.LiveGoodsStatsDetailMapper;
import com.vhall.component.dao.room.RoomGoodsMapper;
import com.vhall.component.entity.goods.GoodsEntity;
import com.vhall.component.entity.goods.LiveGoodsEntity;
import com.vhall.component.entity.goods.LiveGoodsStatsDetailEntity;
import com.vhall.component.entity.goods.goods.*;
import com.vhall.component.entity.goods.vo.GetGoodsInfoRequestVO;
import com.vhall.component.entity.goods.vo.GetGoodsInfoResponseVO;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.entity.room.entity.RoomGoodsEntity;
import com.vhall.component.entity.subject.enums.StatusEnum;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.CollectionUtils;
import com.vhall.component.framework.common.utils.StringUtils;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.properties.ThirdPartyProperties;
import com.vhall.component.plugin.common.support.*;
import com.vhall.component.service.goods.*;
import com.vhall.component.service.goods.assembler.GoodsAssembler;
import com.vhall.component.service.goods.common.GoodsConstant;
import com.vhall.component.service.goods.converter.GoodsConverter;
import com.vhall.component.service.goods.event.LiveGoodsListRefreshEvent;
import com.vhall.component.service.room.RoomInnerService;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author guoxin.wang
 * @date 2021-06-10 15:21
 */
@Slf4j
@Service
public class GoodsConsoleServiceImpl implements GoodsConsoleService {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private LiveGoodsMapper liveGoodsMapper;

    @Resource
    private GoodsAssembler goodsAssembler;

    @Resource
    private GoodsConverter goodsConverter;

    @Autowired
    private RoomInnerService roomInnerService;

    @Autowired
    private LiveGoodsStatsDetailMapper liveGoodsStatsDetailMapper;

    @Autowired
    @Setter
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private LiveGoodsStatsService liveGoodsStatsService;

    @Autowired
    private LiveGoodsConsoleService liveGoodsConsoleService;
    @Resource
    private GuoxinPrdService guoxinPrdService;
    @Resource
    private ThirdPartyProperties thirdPartyProperties;
    @Resource
    private RoomGoodsMapper roomGoodsMapper;

    @Override
    public Boolean create(GoodsConsoleCreateReqVO reqVO) {
        // 根据token获取用户信息
        GoodsEntity goods = goodsConverter.to(reqVO);

        assemblyOperator(goods);

        if (org.apache.commons.lang3.StringUtils.isNotBlank(goods.getGoodsUrlAndroid())) {
            goods.setGoodsUrlIos(goods.getGoodsUrlAndroid());
        }

        goods.setCreatedAt(LocalDateTime.now());
        goods.setLoadOrUnload(StatusEnum.CLOSE.getValue());
        Preconditions.checkArgument(goodsMapper.insert(goods) > 0, "操作失败！");
        return true;

    }

    private void assemblyOperator(GoodsEntity goods) {
        Token accountInfo = TokenThreadLocal.getToken();
        if (accountInfo != null) {
            goods.setAccountId(accountInfo.getAccountId());
        }
    }

    @Override
    public Boolean delete(GoodsConsoleDeleteReqVO reqVO) {
        // 根据token获取用户信息

        List<String> bgIds = reqVO.getBgIds();

        // 检查是否存在
        LambdaQueryWrapper<GoodsEntity> queryGoods = Wrappers.lambdaQuery();
        queryGoods.in(GoodsEntity::getBgId, bgIds).eq(GoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_ON);
        List<GoodsEntity> goods = goodsMapper.selectList(queryGoods);
        if (goods == null || goods.isEmpty()) {
            throw new BusinessException(BizErrorCode.EMPTY_GOODS);
        }
        // 检查是否绑定
        LambdaQueryWrapper<LiveGoodsEntity> where = Wrappers.lambdaQuery();
        where.in(LiveGoodsEntity::getBgId, bgIds).eq(LiveGoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_ON);
        if (liveGoodsMapper.selectCount(where) > 0) {
            throw new BusinessException(BizErrorCode.COMP_GOODS_BIND);
        }
        // 执行软删除
        LambdaUpdateWrapper<GoodsEntity> update = Wrappers.lambdaUpdate();
        update.in(GoodsEntity::getBgId, bgIds);
        update.set(GoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_OFF);
        update.set(GoodsEntity::getUpdatedAt, LocalDateTime.now());
        return goodsMapper.update(null, update) > 0;
    }

    @Override
    public Boolean update(GoodsConsoleUpdateReqVO reqVO) {
        // 根据token获取用户信息
        Token token = TokenThreadLocal.getToken();

        LambdaUpdateWrapper<GoodsEntity> wrapper = Wrappers.lambdaUpdate();

        wrapper.eq(GoodsEntity::getBgId, reqVO.getBgId())
                .set(GoodsEntity::getUpdatedAt, LocalDateTime.now())
                .set(token != null, GoodsEntity::getAccountId, token != null ? token.getAccountId() : null)
                .set(GoodsEntity::getGoodsTag, reqVO.getGoodsTag())
                .set(GoodsEntity::getGoodsUrl, reqVO.getGoodsUrl())
                .set(GoodsEntity::getGoodsUrlAndroid, reqVO.getGoodsUrlAndroid())
                .set(GoodsEntity::getGoodsUrlIos, reqVO.getGoodsUrlAndroid())
                .set(GoodsEntity::getPic, reqVO.getPic())
                .set(GoodsEntity::getProductButtonText, reqVO.getProductButtonText())
                .set(GoodsEntity::getName, reqVO.getName())
        ;


        int updCount = goodsMapper.update(null, wrapper);
        if (updCount <= 0) {
            throw new BusinessException(BizErrorCode.EMPTY_GOODS);
        }

        // 获取商品关联房间，若有直播中的进行刷新消息推送
        List<LiveGoodsEntity> liveGoodsEntities = goodsService.listLiveGoods(reqVO.getBgId());
        if (CollectionUtils.isNotEmpty(liveGoodsEntities)) {
            List<Integer> ilIds = liveGoodsEntities.stream().map(LiveGoodsEntity::getIlId).collect(Collectors.toList());
            // 删除绑定了房间的商品的缓存信息
            for (Integer single : ilIds) {
                liveGoodsConsoleService.delFirstPageGoodsCache(single);
            }
            // 直播间内消息推送
            applicationEventPublisher.publishEvent(new LiveGoodsListRefreshEvent(this, ilIds, "console端商品信息变更"));
        }
        return true;
    }

    @Override
    public GoodsRspVO get(GoodsDetailReqVO reqVO) {
        LambdaQueryWrapper<GoodsEntity> query = Wrappers.lambdaQuery();
        query.eq(GoodsEntity::getBgId, reqVO.getBgId());
        query.eq(GoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_ON);
        GoodsEntity goods = goodsMapper.selectOne(query);
        if (Objects.isNull(goods)) {
            throw new BusinessException(BizErrorCode.EMPTY_GOODS);
        }
        // 如果要上报的话。
        if (reqVO.getIsReport() != null && reqVO.getIsReport().equals(GoodsConstant.REPORT_ON)) {
            VssToken accountInfo = VssTokenThreadLocal.getToken();
            RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
            if (Objects.isNull(roomInfo)) {
                throw new BusinessException(BizErrorCode.EMPTY_ROOM);
            }
            int bgId = reqVO.getBgId().intValue();
            LiveGoodsStatsDetailEntity param = new LiveGoodsStatsDetailEntity();
            param.setBgId(bgId);
            param.setIlId(roomInfo.getIlId());
            param.setType(GoodsConstant.OPERATE_TYPE_CLICK);
            param.setUserId(accountInfo.getThirdPartyUserId());
            LocalDateTime now = LocalDateTime.now();
            param.setCreatedAt(now);
            liveGoodsStatsDetailMapper.insert(param);
            liveGoodsStatsService.handleIncrGoodsStatsPvUv(bgId, roomInfo.getIlId(), accountInfo.getThirdPartyUserId(), now);
        }
        return goodsAssembler.goodsEntityToRspVo(goods);
    }

    @Override
    public GoodsPageVO<GoodsRspVO> list(GoodsConsoleListReqVO reqVO) {

        LambdaQueryWrapper<GoodsEntity> where = Wrappers.lambdaQuery();

        // 如果传送房间号，这里要统计，当前房间关联产品数量
        int size = 0;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(reqVO.getRoomId())) {

            RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());

            LambdaQueryWrapper<LiveGoodsEntity> queryGoods = Wrappers.lambdaQuery();
            queryGoods.eq(LiveGoodsEntity::getIlId, roomInfo.getIlId())
                    .eq(LiveGoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_ON);
            List<LiveGoodsEntity> liveGoodsEntities = liveGoodsMapper.selectList(queryGoods);
            if (CollectionUtils.isNotEmpty(liveGoodsEntities)) {
                List<LiveGoodsEntity> liveGoodsEntities1 = liveGoodsEntities.stream().filter(e -> e.getDeletedAt() == null).collect(Collectors.toList());
                size = liveGoodsEntities1.size();

                if (CollectionUtils.isNotEmpty(liveGoodsEntities1)) {
                    where.notIn(GoodsEntity::getBgId, liveGoodsEntities1.stream().map(LiveGoodsEntity::getBgId).collect(Collectors.toList()));
                }

            }
        }


        where.eq(GoodsEntity::getGoodsStatus, GoodsConstant.GOODS_STATUS_ON);
        if (reqVO.getLoadOrUnload() != null && reqVO.getLoadOrUnload() != -1) {
            where.eq(GoodsEntity::getLoadOrUnload, reqVO.getLoadOrUnload());
        }
        where.and(StringUtils.isNotEmpty(reqVO.getKeyword()),
                w -> w.like(GoodsEntity::getName, reqVO.getKeyword()).or().like(GoodsEntity::getBgId, reqVO.getKeyword()));
        where.orderByDesc(GoodsEntity::getBgId);
        Page<GoodsEntity> page = new Page<>(reqVO.getPage(), reqVO.getPageSize());
        page = goodsMapper.selectPage(page, where);
        List<GoodsRspVO> list = goodsAssembler.goodsEntitiesToRspVos(page.getRecords());
        return new GoodsPageVO<>(reqVO.getPage(), reqVO.getPageSize(), (int) page.getTotal(), list, size);
    }

    @Override
    public Boolean loadOrUnload(GoodsLoadOrUnloadReqVO reqVO) {

        LambdaUpdateWrapper<GoodsEntity> update = Wrappers.lambdaUpdate();
        update.eq(GoodsEntity::getBgId, reqVO.getBgId());
        update.set(GoodsEntity::getLoadOrUnload, reqVO.getLoadOrUnload());
        update.set(GoodsEntity::getUpdatedAt, LocalDateTime.now());
        return goodsMapper.update(null, update) > 0;
    }

    /**
     *
     * @param reqVO
     * @return
     */
    @Override
    public GetGoodsInfoResponseVO detail(GoodsDetailReqVO reqVO) {
        Integer bgId = reqVO.getBgId().intValue();
        RoomGoodsEntity roomGoodsEntity = roomGoodsMapper.selectById(bgId);
        if (roomGoodsEntity == null){
            throw new BusinessException(60000,"未查询到商品信息,关联ID错误","");
        }

        GetGoodsInfoRequestVO vo = new GetGoodsInfoRequestVO();
        vo.setPrdCodes(roomGoodsEntity.getPrdType() + "." + roomGoodsEntity.getPrdCode());
        vo.setIlId(roomGoodsEntity.getIlId());
        List<GetGoodsInfoResponseVO> goodsInfoList = guoxinPrdService.getGoodsInfoList(vo);

        if (reqVO.getIsReport() == 1){
            VssToken token = VssTokenThreadLocal.getToken();
            RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
            LiveGoodsStatsDetailEntity liveGoodsStatsDetailEntity = new LiveGoodsStatsDetailEntity();
            liveGoodsStatsDetailEntity.setIlId(roomInfo.getIlId());
            liveGoodsStatsDetailEntity.setBgId(Math.toIntExact(reqVO.getBgId()));
            liveGoodsStatsDetailEntity.setUserId(token.getThirdPartyUserId());
            liveGoodsStatsDetailEntity.setType(1);
            liveGoodsStatsDetailMapper.insert(liveGoodsStatsDetailEntity);
        }

        if (CollUtil.isNotEmpty(goodsInfoList)) {
            return goodsInfoList.get(0);
        }
        return new GetGoodsInfoResponseVO();
    }


}
